package com.flyxiaozhu.erp.admin.controllers;

import com.flyxiaozhu.erp.core.entities.Role;
import com.flyxiaozhu.erp.core.entities.RolePermission;
import com.flyxiaozhu.erp.core.libs.ErrorCode;
import com.flyxiaozhu.erp.core.libs.JSONResult;
import com.flyxiaozhu.erp.core.libs.SearchSpecification;
import com.flyxiaozhu.erp.core.repositories.RolePermissionRepository;
import com.flyxiaozhu.erp.core.repositories.RoleRepository;
import com.flyxiaozhu.erp.core.utils.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.util.*;

@RestController
public class RoleController {
    @Autowired
    RoleRepository roleRepository;

    @Autowired
    RolePermissionRepository rolePermissionRepository;

    @Secured("ROLE_ROLE_SELECT")
    @RequestMapping("/role/select")
    public JSONResult select(HttpServletRequest request, @PageableDefault Pageable pageable) {
        Page<Role> page = roleRepository.findAll(new SearchSpecification<>(request), pageable);
        List<Long> rolesId = CollectionUtils.map(page.getContent(), Role::getId);
        List<RolePermission> permissions = rolePermissionRepository.findByRoleIdIn(rolesId);
        Map<Long, List<Long>> perms = CollectionUtils.group(permissions, new CollectionUtils.GroupFilter<RolePermission, Long, Long>() {
            @Override
            public Long getKey(RolePermission source) {
                return source.getRoleId();
            }

            @Override
            public Long getValue(RolePermission source) {
                return source.getPermissionId();
            }
        });

        for (Role role : page.getContent()) {
            if (perms.containsKey(role.getId())) {
                role.setPerms(perms.get(role.getId()));
            }
        }

        return new JSONResult(page, pageable.getPageNumber());
    }

    @Secured("ROLE_ROLE_INSERT")
    @RequestMapping("/role/insert")
    public JSONResult insert(@RequestParam("name") String name,
                             @RequestParam(value = "perms", required = false) List<Long> perms) {
        if (roleRepository.findByName(name) != null) {
            return new JSONResult(ErrorCode.NO_DATA, "角色名已存在");
        }

        Role role = new Role();
        role.setName(name);
        roleRepository.save(role);

        if (perms != null && perms.size() > 0) {
            putPerms(role.getId(), perms);
        }

        role.setPerms(perms);
        return new JSONResult().put("model", role);
    }

    @Secured("ROLE_ROLE_UPDATE")
    @RequestMapping("/role/update")
    @Transactional
    public JSONResult update(@RequestParam("id") Long id,
                             @RequestParam("name") String name,
                             @RequestParam(value = "perms", required = false) List<Long> perms) {
        Role role = roleRepository.findById(id).orElse(null);
        if (role == null) {
            return new JSONResult(ErrorCode.NO_DATA, "角色ID错误");
        }

        Role old = roleRepository.findByName(name);
        if (old != null && old.getId() != id) {
            return new JSONResult(ErrorCode.NO_DATA, "角色名已存在");
        }

        role.setName(name);
        roleRepository.save(role);

        rolePermissionRepository.deleteAllByRoleId(role.getId());

        if (perms != null && perms.size() > 0) {
            putPerms(role.getId(), perms);
        }

        role.setPerms(perms);
        return new JSONResult().put("model", role).put("count", 1);
    }

    private void putPerms(Long roleId, Collection<Long> perms) {
        for (Long permId : perms) {
            RolePermission rp = new RolePermission();
            rp.setPermissionId(permId);
            rp.setRoleId(roleId);
            rolePermissionRepository.save(rp);
        }
    }
}
